package com.itlong.cloud.property.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.property.PadUserAuthPushDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyPaymentPageDTO;
import com.itlong.cloud.POJO.DTO.property.PropertySaveMeterInfoDTO;
import com.itlong.cloud.POJO.DTO.property.PropertySaveMeterInfoSubDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.property.PropertyGetManagementPageVO;
import com.itlong.cloud.POJO.VO.property.PropertyPaymentGetPageVO;
import com.itlong.cloud.POJO.VO.property.PropertyGetMeterInfoVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IPropertyAccountDao;
import com.itlong.cloud.property.dao.IPropertyPaymentDataRecordDao;
import com.itlong.cloud.property.dao.IPropertyPaymentManageDao;
import com.itlong.cloud.property.dao.IPropertyRoomInfoDao;
import com.itlong.cloud.property.service.IPropertyPaymentManageService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * <desc>
 *      物业收费管理业务处理接口实现类
 * </desc>
 *
 * @createDate 2018/08/15
 */
@Service
public class PropertyPaymentManageServiceImpl implements IPropertyPaymentManageService {
    @Autowired
    IPropertyPaymentManageDao iPropertyPaymentManageDao;

    @Autowired
    IPropertyPaymentDataRecordDao iPropertyPaymentDataRecordDao;

    @Autowired
    RedisService redisService;

    @Autowired
    IPropertyRoomInfoDao iPropertyRoomInfoDao;

    @Autowired
    IPropertyAccountDao iPropertyAccountDao;

    @Autowired
    MessageSender messageSender;
    /**
     * <desc>
     *     获取抄表分页数据
     * </desc>
     *
     * @param pageDTO   参数DTO
     * @return
     * @author Jiaqi.X
     * @createDate 2018/08/15
     */
    @Override
    public Page<PropertyPaymentGetPageVO> getMeterInfoByPage(PropertyPaymentPageDTO pageDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
        if(StringUtils.isNotBlank(pageDTO.getFeeDataIds())){
            params.put("feeDataIds",StringHandlerUtil.splitString(pageDTO.getFeeDataIds()));
        }
        //分页类默认pageSize为20
        Page<PropertyPaymentGetPageVO> page = new Page<>();
        page.getPage().setPageSize(pageDTO.getPageSize());
        page.getPage().setCurrentPage(pageDTO.getCurrentPage());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        if(StringUtils.isNotBlank(pageDTO.getExport()) && pageDTO.getExport().equals("1")){
            params.put("pageSize",2000);
        }
        List<PropertyPaymentGetPageVO> list = iPropertyPaymentManageDao.getMeterMainPage(params);
        for(PropertyPaymentGetPageVO vo : list){
            //转换时间格式
            String startTime = vo.getMonth().substring(0, vo.getMonth().indexOf("y"));
            String endTime = vo.getMonth().substring(vo.getMonth().indexOf("y") + 1, vo.getMonth().length());
            Date startMonth = DateUtil.formatStringToDate(startTime,"yyyy-MM");
            Date endMonth = DateUtil.formatStringToDate(endTime,"yyyy-MM");
            Calendar start = Calendar.getInstance();
            start.setTime(startMonth);
            Calendar end = Calendar.getInstance();
            end.setTime(endMonth);
            if(start.get(Calendar.MONTH) == end.get(Calendar.MONTH)){
                vo.setMonth(startTime);
            }else if(start.getTime().getTime() < end.getTime().getTime()){
                vo.setMonth(startTime+"~"+StringHandlerUtil.autlSupply(2,""+(end.get(Calendar.MONTH)+1),"0"));
            }
            //查询子集
            params.put("feeIds", StringHandlerUtil.splitString(vo.getFeeDataId()));
            vo.setCosts(iPropertyPaymentManageDao.getMeterSubList(params));
        }
        //填充返回数据集
        page.setRows(list, iPropertyPaymentManageDao.getMeterMainPageCount(params));
        return page;
    }


    /**
     * <desc>
     *     获取物业费分页数据
     * </desc>
     *
     * @param pageDTO   参数DTO
     * @return
     * @author Jiaqi.X
     * @createDate 2018/08/20
     */
    @Override
    public Page<PropertyGetManagementPageVO> getManagementInfoByPage(PropertyPaymentPageDTO pageDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
        if(StringUtils.isNotBlank(pageDTO.getFeeDataIds())){
            params.put("feeDataIds",StringHandlerUtil.splitString(pageDTO.getFeeDataIds()));
        }
        //分页类默认pageSize为20
        Page<PropertyGetManagementPageVO> page = new Page<>();
        page.getPage().setPageSize(pageDTO.getPageSize());
        page.getPage().setCurrentPage(pageDTO.getCurrentPage());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        if(StringUtils.isNotBlank(pageDTO.getExport()) && pageDTO.getExport().equals("1")){
            params.put("pageSize",2000);
        }
        List<PropertyGetManagementPageVO> list = iPropertyPaymentManageDao.getManagementPage(params);
        for(PropertyGetManagementPageVO vo : list){
            //转换时间格式
            String startTime = vo.getMonth().substring(0, vo.getMonth().indexOf("y"));
            String endTime = vo.getMonth().substring(vo.getMonth().indexOf("y") + 1, vo.getMonth().length());
            Date startMonth = DateUtil.formatStringToDate(startTime, "yyyy-MM");
            Date endMonth = DateUtil.formatStringToDate(endTime, "yyyy-MM");
            Calendar start = Calendar.getInstance();
            start.setTime(startMonth);
            Calendar end = Calendar.getInstance();
            end.setTime(endMonth);
            if(start.get(Calendar.MONTH) == end.get(Calendar.MONTH)){
                vo.setMonth(startTime);
            }else if(start.getTime().getTime() < end.getTime().getTime()){
                vo.setMonth(startTime+"~"+StringHandlerUtil.autlSupply(2,""+(end.get(Calendar.MONTH)+1),"0"));
            }
        }
        //填充返回数据集
        page.setRows(list, iPropertyPaymentManageDao.getManagementPageCount(params));
        return page;
    }

    /**
     * <desc>
     *      删除录入数据
     * </desc>
     *
     * @param feeDataId
     * @return
     * @author Jiaqi.X
     * @createDate 2018/08/20
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer deletePaymentRecord(String feeDataId) throws Exception {
        String[] feeDataIds = StringHandlerUtil.splitString(feeDataId);
        //查询录入数据，及关联feeId的集合
        List<PropertyPaymentDataRecordPO> list = iPropertyPaymentDataRecordDao.getSmallFeeListByFeeDataId(StringHandlerUtil.splitString(feeDataId),null);
        Optional<PropertyPaymentDataRecordPO> optional = list.stream().filter(record -> record.getFeeId()!=null).findFirst();
        if((optional.isPresent()&&optional.get().getFeeStatus()!=2)&&((optional.isPresent() && optional.get().getType()==4 && list.size( )== 1)||
                (optional.isPresent() && optional.get().getType()!=4 && list.size( )== 3))){
            //删除账单
            iPropertyPaymentManageDao.deleteBillByFeeId(optional.get().getFeeId());
        }else if(optional.isPresent()){
            //重新计算账单金额
            BigDecimal subtractTotal = new BigDecimal(0);
            BigDecimal penaltyTotal = new BigDecimal(0);
            BigDecimal addTotal = new BigDecimal(0);
            PropertyPaymentBillPO propertyPaymentBillPO = iPropertyPaymentManageDao.getBillByFeeId(optional.get().getFeeId());
            for(PropertyPaymentDataRecordPO po : list){
                boolean check = false;
                for(String id : feeDataIds){
                    if(id.equals(po.getFeeDataId()) && (propertyPaymentBillPO.getFeeStatus()==1)){
                        check = true;
                    }
                }
                if(!check){
                    subtractTotal=subtractTotal.add(po.getDueAmount());
                    penaltyTotal=penaltyTotal.add(po.getPenalty());
                    addTotal=addTotal.add(po.getDueAmount().add(po.getPenalty()).add(po.getLossAmount()!=null ? po.getLossAmount() : new BigDecimal(0)));
                }
            }
            for(int i = list.size()-1 ;i >= 0;i--){
                for(String id : feeDataIds){
                    if(list.get(i).getFeeDataId().equals(id)){
                        list.remove(i);
                        break;
                    }
                }
            }
            if(list.get(0).getFeeStatus()==2){
                propertyPaymentBillPO.setFeeStatus(2);
            }
            propertyPaymentBillPO.setStartTime(list.get(0).getStartTime());
            propertyPaymentBillPO.setEndTime(list.get(0).getEndTime());
            propertyPaymentBillPO.setDueAmount(subtractTotal);
            propertyPaymentBillPO.setPaidAmount(addTotal);
            propertyPaymentBillPO.setPenalty(propertyPaymentBillPO.getPenalty().subtract(penaltyTotal));
            propertyPaymentBillPO.setUpdateTime(new Date());
            iPropertyPaymentManageDao.update(SqlUtil.durableData(propertyPaymentBillPO,PlatformConstants.TABLE_UPDATE));
        }
        iPropertyPaymentDataRecordDao.deleteRecordByFeeId(feeDataIds);
        List<String> roomIdList = new ArrayList<>();
        String[] feeIds = StringHandlerUtil.splitString(feeDataId);
        // 通过房间id查询房间下的住户
        String roomId = iPropertyPaymentDataRecordDao.getRoomIdByDataId(feeIds[0]);
        roomIdList.add(roomId);
        //获取与此房间有关的用户
        List<Map<String,Object> > users = iPropertyPaymentManageDao.getArrearRoomUserIds(roomId);
        Integer days = iPropertyAccountDao.getMaxArrearDaysByRoomId(roomId,users.get(0).get("projectId").toString());
        List<String> userIdList = iPropertyRoomInfoDao.getUserIdsByRoomId(roomId);
        //判断房间是否在临时通行中
        Integer tempPass = iPropertyPaymentManageDao.checkRoomInfoIsTempPass(roomId);
        Integer arrearStatus = iPropertyPaymentManageDao.checkRoomInfoIsTempRemove(roomId);
        for (String userId : userIdList) {
            if(tempPass > 0 || arrearStatus > 0){
                continue;
            }
            if (days == null || days <= 0) {
                //修改room_info欠费状态
                iPropertyAccountDao.updateRoomStatus(roomIdList);
                iPropertyRoomInfoDao.updateUserProjectArrearageStatus(roomId, 1, userId);
            }
            // 判断用户项目下是否还有欠费房间，没有则更新用户项目为不欠费状态
            int arrearRoomCount = iPropertyRoomInfoDao.getArrearRoomCount(roomId, userId);
            // 更新用户项目欠费状态
            if (arrearRoomCount == 0) {
                iPropertyRoomInfoDao.updateUserProjectArrearageStatus(roomId,0, userId);
            }
        }
        //TODO  通知云对讲设备更新指令
        //业务指令参数JSONArray
        JSONArray pushRoom = new JSONArray();
        JSONArray jsonArray = new JSONArray();
        List<PadUserAuthPushDTO> dtos = new ArrayList<>();
        users.forEach(user->{
            JSONObject json = new JSONObject();
            json.put("userId", user.get("userId").toString());
            json.put("roomId", roomId);
            jsonArray.add(json);
            PadUserAuthPushDTO dto = new PadUserAuthPushDTO();
            dto.setProjectId(user.get("projectId").toString());
            dto.setRoomId(roomId);
            dto.setUserId(user.get("userId").toString());
            dto.setPushType(PadChangeBusinessEnum.PUSH_USER.getCommandType());
            //12:物业删除录入数据
            dto.setInstructionType(12);
            dto.setSourceSystem(2);
            dtos.add(dto);
            JSONObject j = new JSONObject();
            j.put("roomId", roomId);
            pushRoom.add(j);
        });
        if (!jsonArray.isEmpty()) {
            Map<String,Object> padMessage = new HashMap<>();
            padMessage.put("data",JsonUtil.toJSON(dtos));
            messageSender.send(RabbitMQConstant.RABBITMQ_PAD_USER_AUTH_CHANGE_PUSH_QUEUE,
                    JsonUtil.toJSON(padMessage), RabbitMQConstant.RABBITMQ_EQUIP_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_PAD_USER_AUTH_CHANGE_PUSH_KEY);

            DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_ROOM, jsonArray.toJSONString(), users.get(0).get("projectId").toString());
            DeviceBusinessChangeLogPO deviceBusinessChangeLogPO2 =
                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, pushRoom.toJSONString(), users.get(0).get("projectId").toString());
            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
            List<DeviceBusinessChangeLogPO> changeLogPOS2 = new ArrayList<>();
            changeLogPOS.add(deviceBusinessChangeLogPO);
            changeLogPOS2.add(deviceBusinessChangeLogPO2);
            if (changeLogPOS != null && !changeLogPOS.isEmpty()) {
                JSONObject datajs = new JSONObject();
                datajs.put("data", changeLogPOS);
                messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                        JSON.toJSONString(datajs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
            }
            if (changeLogPOS2 != null && !changeLogPOS2.isEmpty()) {
                JSONObject datajs = new JSONObject();
                datajs.put("data", changeLogPOS2);
                messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                        JSON.toJSONString(datajs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
            }

            //云电梯
            DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                    = new DeviceBusinessElevatorChangeLogPO(users.get(0).get("projectId").toString(),
                    CloudElevatorChangeBusinessEnum.PUSH_USER_ROOM, jsonArray.toJSONString());
            DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO2
                    = new DeviceBusinessElevatorChangeLogPO(users.get(0).get("projectId").toString(),
                    CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD, pushRoom.toJSONString());
            List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
            List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS2 = new ArrayList<>();
            deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
            deviceElevatorChangeLogPOS2.add(deviceBusinessElevatorChangeLogPO2);
            JSONObject datajs1 = new JSONObject();
            datajs1.put("data", deviceElevatorChangeLogPOS);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(datajs1),
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
            JSONObject datajs2 = new JSONObject();
            datajs2.put("data", deviceElevatorChangeLogPOS2);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(datajs2),
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);

            // 云门禁
            List<DeviceBusinessEntranceChangeLogPO> changeEntranceLogPOS = new ArrayList<>();
            List<DeviceBusinessEntranceChangeLogPO> changeEntranceLogPOS2 = new ArrayList<>();
            DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(users.get(0).get("projectId").toString(), CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(pushRoom));
            changeEntranceLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_USER_ROOM, jsonArray, users.get(0).get("projectId").toString()));
            changeEntranceLogPOS2.add(entrancePO);
            JSONObject dataJs2 = new JSONObject();
            dataJs2.put("data", changeEntranceLogPOS);
            //发送云门禁指令
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs2),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );
            JSONObject dataJs3 = new JSONObject();
            dataJs3.put("data", changeEntranceLogPOS2);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs3),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );
        }
        //删除录入数据
        return 1;
    }

    /**
     * <desc>
     *      根据id查询抄表费或物业费
     * </desc>
     *
     * @param feeDataId
     * @param type 1抄表费 2物业费
     * @return
     * @author Jiaqi.X
     * @createDate 2018/08/21
     */
    @Override
    public PropertyGetMeterInfoVO getPaymentInfoById(String feeDataId, String type) {
        String[] feeDataIds = StringHandlerUtil.splitString(feeDataId);
        if(feeDataIds.length == 1 && type.equals("1")){
            //查询该抄表费有关的所有抄表费id+
            feeDataId = iPropertyPaymentDataRecordDao.getFeeDataIdsCorrelation(feeDataId);
            feeDataIds = StringHandlerUtil.splitString(feeDataId);
        }
        //查询录入数据，及关联feeId的集合
        List<PropertyPaymentDataRecordPO> list = iPropertyPaymentDataRecordDao.getFeeListByFeeDataId(feeDataIds,Integer.valueOf(type));
        PropertyGetMeterInfoVO vo = new PropertyGetMeterInfoVO();
        List<PropertySaveMeterInfoSubDTO> costs = new ArrayList<>();
        vo.setMonth(DateUtil.fomatDate(list.get(0).getStartTime(), "yyyy-MM"));
        vo.setBuildId(list.get(0).getBuildId());
        vo.setUnitId(list.get(0).getUnitId());
        vo.setRoomId(list.get(0).getRoomId());
        vo.setBuildName(list.get(0).getBuildName());
        vo.setUnitName(list.get(0).getUnitName());
        vo.setRoomNum(list.get(0).getRoomNum());
        if(type.equals("2")){
            //物业费
            vo.setFeeDataId(list.get(0).getFeeDataId());
            vo.setFeeRuleId(list.get(0).getFeeRuleId());
            vo.setFeeId(list.get(0).getFeeId());
            vo.setRemark(list.get(0).getRemark());
        }else{
            //抄表费
            for(PropertyPaymentDataRecordPO po : list){
                PropertySaveMeterInfoSubDTO dto = new PropertySaveMeterInfoSubDTO();
                dto.setFeeId(po.getFeeId());
                dto.setType(po.getType());
                dto.setFeeDataId(po.getFeeDataId());
                dto.setFeeRuleId(po.getFeeRuleId());
                dto.setEnd(po.getEnd());
                dto.setStart(po.getStart());
                dto.setLossAmount(po.getLossAmount()!=null ? po.getLossAmount().toString() : null);
                costs.add(dto);
            }
            if(!costs.isEmpty()){
                //查询收费规则周期
                vo.setFeeCycle(iPropertyPaymentManageDao.getRuleCycle(costs.get(0).getFeeRuleId()));
            }
            vo.setCosts(costs);
        }
        return vo;
    }


    /**
     * <desc>
     *      批量生成抄表费或物业费数据
     * </desc>
     *
     * @param buildIds 楼栋id,多个逗号分隔
     * @param type 1抄表费 2物业费
     * @param month 收费月份
     * @return
     * @author Jiaqi.X
     * @createDate 2018/08/22
     */
    @Override
    public Integer batchAddPaymentRecord(String buildIds,Integer type,String month) throws ParseException {
        String[] strBuildIds = StringHandlerUtil.splitString(buildIds);
        //查询楼栋下的房间信息，且当月没有生成录入数据的房间
        List<RoomInfoPO> rooms = iPropertyPaymentManageDao.getRoomsByBuildIdsAndMonth(strBuildIds,month,type);
        List<PropertyPaymentDataRecordPO> records = new ArrayList<>();
        for(RoomInfoPO room : rooms){
            if(type == 1){
                //抄表费
                List<Integer> types = MeterInfoTypeEnum.toList();
                for(Integer tp : types){
                    PropertyPaymentDataRecordPO po = new PropertyPaymentDataRecordPO();
                    po.setFeeDataId(LogicIdUtil.bussinessId());
                    po.setStartTime(DateUtil.formatStringToDate(month, "yyyy-MM"));
                    po.setEndTime(DateUtil.getCurrentLastDayMonth(po.getStartTime()));
                    po.setBuildId(room.getBuildId());
                    po.setUnitId(room.getUnitId());
                    po.setRoomId(room.getRoomId());
                    po.setCreateTime(new Date());
                    po.setRealName(room.getRealName());
                    po.setPhoneNum(room.getPhoneNum());
                    po.setStatus(DataStatusEnum.NORMAL.getType());
                    po.setType(tp);
                    po.setProjectId(room.getProjectId());
                    po.setFeeStatus(1);
                    records.add(po);
                }
            }else{
                //物业费
                PropertyPaymentDataRecordPO po = new PropertyPaymentDataRecordPO();
                po.setFeeDataId(LogicIdUtil.bussinessId());
                po.setStartTime(DateUtil.formatStringToDate(month, "yyyy-MM"));
                po.setEndTime(DateUtil.getCurrentLastDayMonth(po.getStartTime()));
                po.setRealName(room.getRealName());
                po.setPhoneNum(room.getPhoneNum());
                po.setBuildId(room.getBuildId());
                po.setUnitId(room.getUnitId());
                po.setRoomId(room.getRoomId());
                po.setCreateTime(new Date());
                po.setProjectId(room.getProjectId());
                po.setType(4);
                po.setFeeStatus(1);
                records.add(po);
            }
        }
        if(records.size() > 0) {
            return iPropertyPaymentDataRecordDao.batchAdd(records);
        }
        return 1;
    }



    /**
     * <desc>
     *      保存抄表、物业费数据
     * </desc>
     *
     * @param dto
     * @return
     * @author Jiaqi.X
     * @createDate 2018/08/17
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public String saveOrUpdateMemterInfo(PropertySaveMeterInfoDTO dto) throws Exception {
        if(StringUtils.isNotBlank(dto.getFeeDataId()) && dto.getSaveType().equals("2") && StringUtils.isNotBlank(iPropertyPaymentManageDao.getFeeIdByFeeDataId(dto.getFeeDataId()))){
            //修改物业费只保存备注
            iPropertyPaymentManageDao.updatePropertyFeeRemark(dto.getFeeDataId(),dto.getRemark());
        }else {
            //获取规则
            FeeRuleInfoPO checkRule;
            if (!dto.getSaveType().equals("2")) {
                checkRule = iPropertyPaymentManageDao.getRuleInfoByRuleId(dto.getFees().get(0).getFeeRuleId());
            } else {
                checkRule = iPropertyPaymentManageDao.getRuleInfoByRuleId(dto.getFeeRuleId());
            }
            String endTime = null;
            String startTime = dto.getMonth();
            if (checkRule.getFeeCycle().equals(FeeCycleEnum.QUARTER.getType().toString())) {
                //季度
                endTime = DateUtil.fomatDate(DateUtil.getCurrentLastDayMonth(
                        DateUtil.formatStringToDate(DateUtil.fomatDate(DateUtil.addCurrentTimeOfMonth(
                                DateUtil.formatStringToDate(dto.getMonth(), DateUtil.YYYYMM), 2), "yyyy-MM-dd"), "yyyy-MM-dd")), DateUtil.YYYYMM);
            } else if (checkRule.getFeeCycle().equals(FeeCycleEnum.YEAR.getType().toString())) {
                //年
                startTime = DateUtil.fomatDate(DateUtil.getCurrentYearFirstDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")), DateUtil.YYYYMM);
                endTime = DateUtil.fomatDate(DateUtil.getCurrentYearLastDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")), DateUtil.YYYYMM);
            } else {
                startTime = DateUtil.fomatDate(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM"), DateUtil.YYYYMM);
            }
            //判断是否是新增
            if (dto.getSaveType().equals("1") && ((StringUtils.isBlank(dto.getFeeDataId()) && dto.getFees() != null && dto.getFees().stream().filter(fee -> fee.getFeeDataId() != null).
                    findFirst().isPresent() == false) || (dto.getFees() != null && dto.getFees().stream().filter(fee -> fee.getFeeDataId() != null).
                    findFirst().isPresent() == false))) {
                //判断当月房间是否已录入过数据
                if (iPropertyPaymentManageDao.checkCurrentMonthHaveBill(dto.getRoomId(), startTime, endTime) > 0) {
                    return "-1";
                }
            } else if (StringUtils.isBlank(dto.getFeeDataId()) && dto.getSaveType().equals("2")) {
                //判断当月是否已存在物业费数据录入
                if (iPropertyPaymentManageDao.checkCurrentMonthHavePropertyFee(dto.getRoomId(), startTime, endTime) > 0) {
                    return "-1";
                }
            }
            //判断是否已存在其他类型的子集
            if ((dto.getFees() == null || dto.getFees().isEmpty()) && dto.getSaveType().equals("1")) {
                PropertyPaymentDataRecordPO po = new PropertyPaymentDataRecordPO();
                //判断是新增还是修改
                if (StringUtils.isBlank(dto.getFeeDataId())) {
                    po.setFeeDataId(LogicIdUtil.bussinessId());
                }
                //如果没有录入抄表数据，直接保存
                po.setBuildId(dto.getBuildId());
                po.setUnitId(dto.getUnitId());
                po.setRoomId(dto.getRoomId());
                po.setStartTime(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM"));
                po.setEndTime(DateUtil.getCurrentLastDayMonth(po.getStartTime()));
                po.setProjectId(dto.getProjectId());
                po.setRemark(dto.getRemark());
                iPropertyPaymentDataRecordDao.save(SqlUtil.durableData(po, PlatformConstants.TABLE_SAVE));
            } else {
                List<PropertyPaymentDataRecordPO> records = new ArrayList<>();
                if (StringUtils.isNotBlank(dto.getFeeDataId()) && dto.getSaveType().equals("1")
                        && !dto.getFees().stream().filter(cost -> cost.getFeeDataId() != null).findFirst().isPresent()) {
                    dto.getFees().get(0).setFeeDataId(dto.getFeeDataId());
                    dto.setFeeDataId(null);
                }
                if (dto.getSaveType().equals("1")) {
                    for (PropertySaveMeterInfoSubDTO subDto : dto.getFees()) {
                        //新增或正常修改缴费信息
                        if (StringUtils.isNotBlank(subDto.getFeeRuleId())) {
                            PropertyPaymentDataRecordPO po = new PropertyPaymentDataRecordPO();
                            po.setBuildId(dto.getBuildId());
                            po.setUnitId(dto.getUnitId());
                            po.setRoomId(dto.getRoomId());
                            po.setFeeDataId(StringUtils.isNotBlank(dto.getFeeDataId()) ? dto.getFeeDataId() : subDto.getFeeDataId());
                            po.setProjectId(dto.getProjectId());
                            po.setStartTime(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM"));
                            po.setEndTime(DateUtil.getCurrentLastDayMonth(po.getStartTime()));
                            po.setType(subDto.getType());
                            po.setStart(subDto.getStart());
                            po.setEnd(subDto.getEnd());
                            po.setLossAmount(StringUtils.isNotBlank(subDto.getLossAmount()) ? new BigDecimal(subDto.getLossAmount()) : new BigDecimal(0));
                            po.setUsageAmount(subDto.getEnd() - subDto.getStart());
                            po.setFeeRuleId(subDto.getFeeRuleId());
                            po.setFeeId(subDto.getFeeId());
                            po.setRemark(dto.getRemark());
                            po.setStatus(DataStatusEnum.NORMAL.getType());
                            records.add(po);
                        }
                    }
                } else {
                    //物业费
                    PropertyPaymentDataRecordPO po = new PropertyPaymentDataRecordPO();
                    po.setBuildId(dto.getBuildId());
                    po.setUnitId(dto.getUnitId());
                    po.setRoomId(dto.getRoomId());
                    po.setFeeDataId(dto.getFeeDataId());
                    po.setProjectId(dto.getProjectId());
                    po.setStartTime(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM"));
                    po.setEndTime(DateUtil.getCurrentLastDayMonth(po.getStartTime()));
                    po.setFeeId(dto.getFeeId());
                    po.setType(4);
                    po.setFeeRuleId(dto.getFeeRuleId());
                    po.setStatus(DataStatusEnum.NORMAL.getType());
                    po.setRemark(dto.getRemark());
                    records.add(po);
                }
                //判断是否已经生成账单
                Optional<PropertyPaymentDataRecordPO> temp = records.stream().filter(record -> StringUtils.isNotBlank(record.getFeeId())).findFirst();
                //账单实体
                PropertyPaymentBillPO propertyPaymentBillPO = null;
                if (temp.isPresent()) {
                    //通过feeid查询已生成账单
                    propertyPaymentBillPO = iPropertyPaymentManageDao.getBillByFeeId(temp.get().getFeeId());
                }
                if (propertyPaymentBillPO == null) {
                    propertyPaymentBillPO = iPropertyPaymentManageDao.getBillByRoomIdAndMonth(dto.getRoomId(), startTime);
                }
                if (propertyPaymentBillPO == null) {
                    propertyPaymentBillPO = new PropertyPaymentBillPO();
                    propertyPaymentBillPO.setDueAmount(new BigDecimal("0"));
                    propertyPaymentBillPO.setPaidAmount(new BigDecimal("0"));
                    propertyPaymentBillPO.setPenalty(new BigDecimal("0"));
                    propertyPaymentBillPO.setStatus(DataStatusEnum.NORMAL.getType());
                    propertyPaymentBillPO.setCreateTime(new Date());
                }
                if (StringUtils.isBlank(propertyPaymentBillPO.getFeeId())) {
                    //生成费用单号 规则年月日+六位流水号，如180720000001
                    String date = DateUtil.fomatDate(new Date(), "yyMMdd");
                    //从缓存中获取流水号
                    String redisKey = RedisConstant.REDIS_PAYMENT_BILL_SERIAL_NUMBER_CACHE + dto.getProjectId() + date;
                    Integer tradeNo = (Integer) redisService.getObject(redisKey, Integer.class);
                    if (tradeNo == null) {
                        //查询数据库中是否有当前流水号，有的话将当前流水号放入缓存中且+1赋值给tradeNo
                        String feeNumber = iPropertyPaymentManageDao.getFeeNumberByDate(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"), dto.getProjectId());
                        if (StringUtils.isBlank(feeNumber)) {
                            tradeNo = 1;
                        } else {
                            tradeNo = Integer.valueOf(feeNumber);
                            tradeNo += 1;
                        }
                    } else {
                        tradeNo += 1;
                    }
                    redisService.set(redisKey, RedisConstant.REDIS_PAYMENT_BILL_SERIAL_NUMBER_CACHE_TIME, tradeNo);
                    propertyPaymentBillPO.setFeeNumber(date + StringHandlerUtil.autlSupply(6, tradeNo.toString(), "0"));
                }
                propertyPaymentBillPO.setBuildId(dto.getBuildId());
                propertyPaymentBillPO.setUnitId(dto.getUnitId());
                propertyPaymentBillPO.setRoomId(dto.getRoomId());
                propertyPaymentBillPO.setType(1);
                propertyPaymentBillPO.setProjectId(dto.getProjectId());
                propertyPaymentBillPO.setFeeStatus(1);
                if (StringUtils.isNotBlank(propertyPaymentBillPO.getFeeId())) {
                    List<PropertyPaymentDataRecordPO> oldRecords;
                    oldRecords = iPropertyPaymentDataRecordDao.getRecordsByFeeId(propertyPaymentBillPO.getFeeId(), records.get(0).getType());
                    if (oldRecords != null && !oldRecords.isEmpty()) {
                        records.addAll(oldRecords);
                    }
                }
                BigDecimal billTotal = new BigDecimal(0);
                BigDecimal recordTotal = new BigDecimal(0);
                BigDecimal penaltyTotal = new BigDecimal(0);
                Integer day = 50;
                for (PropertyPaymentDataRecordPO record : records) {
                    if (record.getFeeStatus() == null) {
                        record.setFeeStatus(1);
                    }
                    if (record.getType() != 4) {
                        record.setUsageAmount(record.getEnd() - record.getStart());
                    }
                    //获取规则
                    FeeRuleInfoPO rule = iPropertyPaymentManageDao.getRuleInfoByRuleId(record.getFeeRuleId());
                    day = Integer.valueOf(rule.getFeeDay()) < day ? Integer.valueOf(rule.getFeeDay()) : day;
                    Map<String, String> area = null;
                    if (dto.getSaveType().equals("2")) {
                        //查询房间的面积信息
                        area = iPropertyPaymentManageDao.getRoomAreaByRoomId(record.getRoomId());
                    }
                    if (rule.getCalculateType().equals(CalculateTypeEnum.UNITPRICE.getType().toString())) {
                        if (rule.getMeasureType().equals(MeasureTypeEnum.UNITPRICE.getType().toString())) {
                            //单价
                            record.setDueAmount(new BigDecimal(rule.getPrice()).multiply(new BigDecimal(record.getEnd() - record.getStart())));
                        } else if (rule.getMeasureType().equals(MeasureTypeEnum.LADDER.getType().toString())) {
                            //阶梯收费
                            List<LadderFeeInfoPO> ladders = iPropertyPaymentManageDao.getLaddersByRuleId(record.getFeeRuleId());
                            BigDecimal total = new BigDecimal(0);
                            for (LadderFeeInfoPO ladder : ladders) {
                                Integer use = 0;
                                Integer max = ladder.getUsageAmountMax() != null ? Integer.valueOf(ladder.getUsageAmountMax()) : null;
                                Integer min = ladder.getUsageAmountMin() != null ? Integer.valueOf(ladder.getUsageAmountMin()) : null;
                                if (min != null && max == null) {
                                    use = record.getUsageAmount() >= min ? record.getUsageAmount() - min : 0;
                                } else if (min != null && max != null) {
                                    if (record.getUsageAmount() >= min && record.getUsageAmount() >= max) {
                                        use = max - min;
                                    } else if (record.getUsageAmount() >= min && record.getUsageAmount() <= max) {
                                        use = record.getUsageAmount() - min;
                                    }
                                }
                                total = total.add(new BigDecimal(ladder.getPrice()).multiply(new BigDecimal(use)));
                            }
                            record.setDueAmount(total);
                        } else if (area != null && rule.getMeasureType().equals(MeasureTypeEnum.BUILDUPAREA.getType().toString())) {
                            record.setDueAmount(StringUtils.isNotBlank(StringHandlerUtil.getNullOrStringForObject(area.get("builtArea")))
                                    ? new BigDecimal(rule.getPrice()).multiply(new BigDecimal(area.get("builtArea").toString())) : new BigDecimal(0));
                        } else if (area != null && rule.getMeasureType().equals(MeasureTypeEnum.INNERAREA.getType().toString())) {
                            record.setDueAmount(StringUtils.isNotBlank(StringHandlerUtil.getNullOrStringForObject(area.get("innerArea")))
                                    ? new BigDecimal(rule.getPrice()).multiply(new BigDecimal(area.get("innerArea").toString())) : new BigDecimal(0));
                        } else if (area != null && rule.getMeasureType().equals(MeasureTypeEnum.PUBLICAREA.getType().toString())) {
                            record.setDueAmount(StringUtils.isNotBlank(StringHandlerUtil.getNullOrStringForObject(area.get("outArea")))
                                    ? new BigDecimal(rule.getPrice()).multiply(new BigDecimal(area.get("outArea").toString())) : new BigDecimal(0));
                        }
                        propertyPaymentBillPO.setStartTime(record.getStartTime());
                    } else if (rule.getCalculateType().equals(CalculateTypeEnum.FIXEDAMOUNT.getType().toString())) {
                        //固定金额
                        propertyPaymentBillPO.setStartTime(record.getStartTime());
                        record.setDueAmount(new BigDecimal(rule.getFixedPrice()));
                    }
                    if (rule.getFeeCycle().equals(FeeCycleEnum.MONTH.getType().toString())) {
                        if (propertyPaymentBillPO.getEndTime() == null ||
                                (propertyPaymentBillPO.getEndTime() != null && record.getEndTime() != null &&
                                        record.getEndTime().getTime() > propertyPaymentBillPO.getEndTime().getTime())) {
                            propertyPaymentBillPO.setEndTime(DateUtil.getCurrentLastDayMonth(record.getStartTime()));
                        }
                        if (propertyPaymentBillPO.getStartTime() != null &&
                                record.getStartTime().getTime() < propertyPaymentBillPO.getStartTime().getTime()) {
                            propertyPaymentBillPO.setEndTime(DateUtil.getCurrentYearLastDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")));
                        }
                    } else if (rule.getFeeCycle().equals(FeeCycleEnum.QUARTER.getType().toString())) {
                        //季度
                        record.setEndTime(DateUtil.getCurrentLastDayMonth(
                                DateUtil.formatStringToDate(DateUtil.fomatDate(DateUtil.addCurrentTimeOfMonth(record.getStartTime(), 2), "yyyy-MM-dd"), "yyyy-MM-dd")));
                        if (propertyPaymentBillPO.getStartTime() != null &&
                                record.getStartTime().getTime() < propertyPaymentBillPO.getStartTime().getTime()) {
                            propertyPaymentBillPO.setEndTime(DateUtil.getCurrentYearLastDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")));
                        }
                        if (propertyPaymentBillPO.getEndTime() == null ||
                                (propertyPaymentBillPO.getEndTime() != null &&
                                        record.getEndTime().getTime() > propertyPaymentBillPO.getEndTime().getTime())) {
                            propertyPaymentBillPO.setEndTime(record.getEndTime());
                        }
                    } else if (rule.getFeeCycle().equals(FeeCycleEnum.YEAR.getType().toString())) {
                        //年
                        record.setEndTime(DateUtil.getCurrentYearLastDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")));
                        record.setStartTime(DateUtil.getCurrentYearFirstDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")));
                        propertyPaymentBillPO.setStartTime(DateUtil.getCurrentYearFirstDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")));
                        if (propertyPaymentBillPO.getEndTime() == null ||
                                (propertyPaymentBillPO.getEndTime() != null &&
                                        record.getEndTime().getTime() > propertyPaymentBillPO.getEndTime().getTime())) {
                            propertyPaymentBillPO.setEndTime(DateUtil.getCurrentYearLastDay(DateUtil.formatStringToDate(dto.getMonth(), "yyyy-MM")));
                        }
                    }
                    record.setPaidAmount(record.getDueAmount().add(record.getLossAmount() != null
                            ? record.getLossAmount() : new BigDecimal(0)).add(record.getPenalty() != null ? record.getPenalty() : new BigDecimal(0)));
                    billTotal = billTotal.add(record.getPaidAmount() != null ? record.getPaidAmount() : new BigDecimal(0));
                    recordTotal = recordTotal.add(record.getDueAmount());
                    penaltyTotal = penaltyTotal.add(record.getPenalty() != null ? record.getPenalty() : new BigDecimal(0));
                }
                //计算账单总价
                propertyPaymentBillPO.setDueAmount(recordTotal);
                propertyPaymentBillPO.setPaidAmount(billTotal);
                propertyPaymentBillPO.setPenalty(penaltyTotal);
                if (billTotal.doubleValue() > 999999999.99) {
                    return String.format("添加%s失败，原因：计算总金额为%s 超过系统存储的最大金额限制。", dto.getSaveType().equals("1") ? "抄表费" : "物业费", billTotal.doubleValue());
                }
                //入库
                //查询当前住户的信息
                Map<String, Object> userInfo = iPropertyPaymentManageDao.getUserPhoneByRoomId(dto.getRoomId());
                if (StringUtils.isBlank(propertyPaymentBillPO.getFeeId())) {
                    propertyPaymentBillPO.setFeeId(LogicIdUtil.bussinessId());
                    if (userInfo != null) {
                        propertyPaymentBillPO.setRealName(StringHandlerUtil.getNullOrStringForObject(userInfo.get("realName")));
                        propertyPaymentBillPO.setPhoneNum(StringHandlerUtil.getNullOrStringForObject(userInfo.get("phoneNum")));
                    }
                    iPropertyPaymentManageDao.save(SqlUtil.durableData(propertyPaymentBillPO, PlatformConstants.TABLE_SAVE));
                } else {
                    if (userInfo != null) {
                        propertyPaymentBillPO.setRealName(StringHandlerUtil.getNullOrStringForObject(userInfo.get("realName")));
                        propertyPaymentBillPO.setPhoneNum(StringHandlerUtil.getNullOrStringForObject(userInfo.get("phoneNum")));
                    }
                    propertyPaymentBillPO.setUpdateTime(new Date());
                    iPropertyPaymentManageDao.update(SqlUtil.durableData(propertyPaymentBillPO, PlatformConstants.TABLE_UPDATE));
                }
                for (PropertyPaymentDataRecordPO record : records) {
                    record.setFeeId(propertyPaymentBillPO.getFeeId());
                    if (StringUtils.isNotBlank(record.getFeeDataId())) {
                        if (userInfo != null) {
                            record.setPhoneNum(StringHandlerUtil.getNullOrStringForObject(userInfo.get("phoneNum")));
                            record.setRealName(StringHandlerUtil.getNullOrStringForObject(userInfo.get("realName")));
                        }
                        record.setUpdateTime(new Date());
                        iPropertyPaymentDataRecordDao.update(SqlUtil.durableData(record, PlatformConstants.TABLE_UPDATE));
                    } else {
                        if (userInfo != null) {
                            record.setPhoneNum(StringHandlerUtil.getNullOrStringForObject(userInfo.get("phoneNum")));
                            record.setRealName(StringHandlerUtil.getNullOrStringForObject(userInfo.get("realName")));
                        }
                        record.setFeeDataId(LogicIdUtil.bussinessId());
                        record.setCreateTime(new Date());
                        iPropertyPaymentDataRecordDao.save(SqlUtil.durableData(record, PlatformConstants.TABLE_SAVE));
                    }
                }
                if (propertyPaymentBillPO.getPaidAmount().doubleValue() > 0 && StringUtils.isNotBlank(propertyPaymentBillPO.getPhoneNum())) {
                    //查询该房间下的所有住户手机号
                    List<String> phoneNums = iPropertyPaymentManageDao.getUserPhonesByRoomId(dto.getRoomId());
                    if (phoneNums != null && !phoneNums.isEmpty()) {
                        //发送用户账单极光推送
                        Map<String, Object> params = new HashMap<>();
                        //查询用户手机号
                        System.out.println(JsonUtil.toJSON(phoneNums));
                        params.put("phoneNum", JsonUtil.toJSON(phoneNums));
                        params.put("projectId", dto.getProjectId());
                        params.put("feeId", propertyPaymentBillPO.getFeeId());
                        params.put("message", String.format("您在%s有新的未缴账单 共%s元", iPropertyPaymentManageDao.getProjectNameByProjectId(dto.getProjectId()), propertyPaymentBillPO.getPaidAmount()));
                        messageSender.send(RabbitMQConstant.RABBITMQ_PAYMENT_BILL_JPUSH_QUEUE, JsonUtil.toJSON(params),
                                RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_EXCHANGE, RabbitMQConstant.RABBITMQ_PAYMENT_BILL_JPUSH_KEY);
                    }
                }
                //判断房间是否欠费
                //计算欠费时间
                Date time = DateUtil.formatStringToDate(DateUtil.fomatDate(records.get(0).getStartTime(), "yyyy-MM-dd"), "yyyy-MM-dd");
                time = DateUtil.getAddMonth(time, 1);
                time = day.toString().equals("1") ? time : DateUtil.getAddDay(time, day - 1);
                //计算当前欠费了多少天
                Integer arrearsDay = Integer.valueOf(DateUtil.reckonDate(DateUtil.fomatDate(new Date(), "yyyy-MM-dd HH:mm:ss"), DateUtil.fomatDate(time, "yyyy-MM-dd HH:mm:ss")).get("day").toString());
                if (arrearsDay > 0 && billTotal.doubleValue() > 0) {
                    //房间欠费，修改房间状态
                    //判断房间是否在临时通行中
                    Integer tempPass = iPropertyPaymentManageDao.checkRoomInfoIsTempPass(dto.getRoomId());
                    Integer arrearStatus = iPropertyPaymentManageDao.checkRoomInfoIsTempRemove(dto.getRoomId());
                    if (tempPass == 0 && arrearStatus == 0) {
                        //修改房间欠费状态
                        iPropertyPaymentManageDao.updateRoomStatus(dto.getRoomId());
                        //获取与此房间有关的用户
                        List<Map<String, Object>> users = iPropertyPaymentManageDao.getArrearRoomUserIds(dto.getRoomId());
                        //TODO  通知云对讲设备更新指令
                        //业务指令参数JSONArray
                        JSONArray jsonArray = new JSONArray();
                        List<PadUserAuthPushDTO> dtos = new ArrayList<>();
                        //修改用户项目欠费状态
                        users.forEach(user -> {
                            iPropertyPaymentManageDao.updateUserProjectStatus(user);
                            JSONObject json = new JSONObject();
                            json.put("userId", user.get("userId").toString());
                            json.put("roomId", dto.getRoomId());
                            jsonArray.add(json);
                            PadUserAuthPushDTO padDTO = new PadUserAuthPushDTO();
                            padDTO.setProjectId(user.get("projectId").toString());
                            padDTO.setRoomId(dto.getRoomId());
                            padDTO.setUserId(user.get("userId").toString());
                            padDTO.setPushType(PadChangeBusinessEnum.PUSH_USER.getCommandType());
                            // 保存抄表或物业费
                            padDTO.setInstructionType(13);
                            padDTO.setSourceSystem(2);
                            dtos.add(padDTO);
                        });
                        if (!jsonArray.isEmpty()) {
                            //发送平板指令
                            Map<String, Object> padMessage = new HashMap<>();
                            padMessage.put("data", JsonUtil.toJSON(dtos));
                            messageSender.send(RabbitMQConstant.RABBITMQ_PAD_USER_AUTH_CHANGE_PUSH_QUEUE,
                                    JsonUtil.toJSON(padMessage), RabbitMQConstant.RABBITMQ_EQUIP_EXCHANGE,
                                    RabbitMQConstant.RABBITMQ_PAD_USER_AUTH_CHANGE_PUSH_KEY);
                            DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_ROOM, jsonArray.toJSONString(), dto.getProjectId());
                            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
                            changeLogPOS.add(deviceBusinessChangeLogPO);
                            if (changeLogPOS != null && !changeLogPOS.isEmpty()) {
                                JSONObject datajs = new JSONObject();
                                datajs.put("data", changeLogPOS);
                                messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                                        JSON.toJSONString(datajs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                                        RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                            }

                            //云电梯
                            DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                                    = new DeviceBusinessElevatorChangeLogPO(dto.getProjectId(),
                                    CloudElevatorChangeBusinessEnum.PUSH_USER_ROOM, jsonArray.toJSONString());
                            List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
                            deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
                            JSONObject datajs1 = new JSONObject();
                            datajs1.put("data", deviceElevatorChangeLogPOS);
                            messageSender.send(
                                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                                    JsonUtil.toJSON(datajs1),
                                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);

                            // 云门禁
                            List<DeviceBusinessEntranceChangeLogPO> changeEntranceLogPOS = new ArrayList<>();
                            changeEntranceLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_USER_ROOM, jsonArray, dto.getProjectId()));
                            JSONObject dataJs2 = new JSONObject();
                            dataJs2.put("data", changeEntranceLogPOS);
                            //发送云门禁指令
                            messageSender.send(
                                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                                    JSON.toJSONString(dataJs2),
                                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
                            );
                        }
                    }
                }
            }
            JSONArray pushRoom = new JSONArray();
            JSONObject j = new JSONObject();
            j.put("roomId", dto.getRoomId());
            pushRoom.add(j);
            //云对讲
            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
            DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, pushRoom.toJSONString(), dto.getProjectId());
            changeLogPOS.add(deviceBusinessChangeLogPO);
            JSONObject datajs = new JSONObject();
            datajs.put("data", changeLogPOS);
            messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                    JsonUtil.toJSON(datajs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
            //云电梯
            DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                    = new DeviceBusinessElevatorChangeLogPO(dto.getProjectId(),
                    CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD, pushRoom.toJSONString());
            List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
            deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
            datajs = new JSONObject();
            datajs.put("data", deviceElevatorChangeLogPOS);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(datajs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
            List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
            DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(dto.getProjectId(), CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(pushRoom));
            entranceChanges.add(entrancePO);
            // 发送云门禁指令
            JSONObject dataJs = new JSONObject();
            dataJs.put("data", entranceChanges);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );
        }

        return "1";
    }


    /**
     * <desc>
     *      导入物业费数据
     * </desc>
     *
     * @param propertySaveMeterInfoDTOs
     * @author Jiaqi.X
     * @createDate 2018/08/30
     */
    public void importSavePropertyFees(@RequestBody List<PropertySaveMeterInfoDTO> propertySaveMeterInfoDTOs) throws Exception {
        //组装数据
        //查询房间信息
        for(PropertySaveMeterInfoDTO dto : propertySaveMeterInfoDTOs){
            dto.setAddress(dto.getAddress().replace(" ",""));
            String buildName = dto.getAddress().substring(0, dto.getAddress().indexOf("-"));
            dto.setAddress(dto.getAddress().substring(dto.getAddress().indexOf("-") + 1,  dto.getAddress().length()));
            String unitName =  dto.getAddress().substring(0, dto.getAddress().indexOf("-"));
            dto.setAddress(dto.getAddress().substring(dto.getAddress().indexOf("-") + 1,  dto.getAddress().length()));
            String roomNum = StringHandlerUtil.autlSupply(4,  dto.getAddress().substring(dto.getAddress().indexOf("-", 2) + 1,  dto.getAddress().length()), "0");
            Map<String,Object> map = iPropertyPaymentManageDao.getRoomInfoByBuildNameAndUnitNameAndRoomNum(buildName,unitName,roomNum,propertySaveMeterInfoDTOs.get(0).getProjectId());
            if(map.get("roomId")!=null && map.get("buildId")!=null && map.get("unitId")!=null){
                dto.setBuildId(map.get("buildId").toString());
                dto.setUnitId(map.get("unitId").toString());
                dto.setRoomId(map.get("roomId").toString());
                //查询规则
                dto.setFeeRuleId(iPropertyPaymentManageDao.getRuleIdByRuleName(propertySaveMeterInfoDTOs.get(0).getProjectId(), dto.getRule(), 2));
                dto.setSaveType("2");
                dto.setProjectId(propertySaveMeterInfoDTOs.get(0).getProjectId());
                if(StringUtils.isNotBlank(dto.getFeeRuleId())){
                    this.saveOrUpdateMemterInfo(dto);
                }
            }
        }
    }

    /**
     * <desc>
     *      检测导入数据的规则是否合法
     * </desc>
     *
     * @param roomName
     * @param ruleName
     * @param type 1抄表费 2物业费
     * @return
     * @author Jiaqi.X
     * @createDate 2018/10/17
     */
    @Override
    public Integer checkImportDataRuleTime(String roomName,String ruleName,Integer type,String projectId,String month) throws ParseException {
        //获取房间id
        roomName = roomName.replace(" ","");
        String buildName = roomName.substring(0, roomName.indexOf("-"));
        roomName = roomName.substring(roomName.indexOf("-") + 1, roomName.length());
        String unitName =  roomName.substring(0, roomName.indexOf("-"));
        roomName = roomName.substring(roomName.indexOf("-") + 1, roomName.length());
        String roomNum = StringHandlerUtil.autlSupply(4,  roomName.substring(roomName.indexOf("-", 2) + 1, roomName.length()), "0");
        Map<String,Object> map = iPropertyPaymentManageDao.getRoomInfoByBuildNameAndUnitNameAndRoomNum(buildName,unitName,roomNum,projectId);
        if(map!=null && map.get("roomId")!=null){
            //获取规则
            FeeRuleInfoPO checkRule = iPropertyPaymentManageDao.getRuleInfoByRuleName(ruleName, projectId);
            String endTime = null;
            String startTime = month;
            if(checkRule.getFeeCycle().equals(FeeCycleEnum.QUARTER.getType().toString())){
                //季度
                endTime=DateUtil.fomatDate(DateUtil.getCurrentLastDayMonth(
                        DateUtil.formatStringToDate(DateUtil.fomatDate(DateUtil.addCurrentTimeOfMonth(
                                DateUtil.formatStringToDate(month, DateUtil.YYYYMM), 2), "yyyy-MM-dd"), "yyyy-MM-dd")),DateUtil.YYYYMM);
            }if(checkRule.getFeeCycle().equals(FeeCycleEnum.YEAR.getType().toString())){
                //年
                startTime = DateUtil.fomatDate(DateUtil.getCurrentYearFirstDay(DateUtil.formatStringToDate(month, "yyyy-MM")),DateUtil.YYYYMM);
                endTime =  DateUtil.fomatDate(DateUtil.getCurrentYearLastDay(DateUtil.formatStringToDate(month, "yyyy-MM")),DateUtil.YYYYMM);
            }else{
                startTime =  DateUtil.fomatDate(DateUtil.formatStringToDate(startTime, "yyyy-MM"),DateUtil.YYYYMM);
            }
            //判断是否是新增
            if(type == 1){
                //判断当月房间是否已录入过数据
                return iPropertyPaymentManageDao.checkCurrentMonthHaveBill(map.get("roomId").toString(), startTime,endTime);
            }else if(type == 2){
                //判断当月是否已存在物业费数据录入
                return iPropertyPaymentManageDao.checkCurrentMonthHavePropertyFee(map.get("roomId").toString(), startTime, endTime);
            }
        }
        return 0;
    }

    /**
     * <desc>
     *      导入抄表费
     * </desc>
     *
     * @param propertySaveMeterInfoDTOs
     * @author Jiaqi.X
     * @createDate 2018/08/30
     */
    @Override
    public String importSaveMeterInfoFees(List<PropertySaveMeterInfoDTO> propertySaveMeterInfoDTOs) throws Exception {
        //组装数据
        //查询房间信息
        Set<Map<String,String>> roomIds = new HashSet<>();
        for(PropertySaveMeterInfoDTO dto : propertySaveMeterInfoDTOs){
            dto.setAddressName(dto.getAddress());
            dto.setAddress(dto.getAddress().replace(" ",""));
            String buildName = dto.getAddress().substring(0, dto.getAddress().indexOf("-"));
            dto.setAddress(dto.getAddress().substring(dto.getAddress().indexOf("-") + 1,  dto.getAddress().length()));
            String unitName =  dto.getAddress().substring(0, dto.getAddress().indexOf("-"));
            dto.setAddress(dto.getAddress().substring(dto.getAddress().indexOf("-") + 1,  dto.getAddress().length()));
            String roomNum = StringHandlerUtil.autlSupply(4,  dto.getAddress().substring(dto.getAddress().indexOf("-", 2) + 1,  dto.getAddress().length()), "0");
            Map<String,Object> map = iPropertyPaymentManageDao.getRoomInfoByBuildNameAndUnitNameAndRoomNum(buildName,unitName,roomNum,propertySaveMeterInfoDTOs.get(0).getProjectId());
            if(map.get("roomId")!=null && map.get("buildId") != null && map.get("unitId") != null){
                dto.setBuildId(map.get("buildId").toString());
                dto.setUnitId(map.get("unitId").toString());
                dto.setRoomId(map.get("roomId").toString());
                Map<String,String> room = new HashMap<>();
                room.put("roomId",dto.getRoomId());
                room.put("address", dto.getAddressName());
                room.put("month",dto.getMonth());
                roomIds.add(room);
            }
        }
        List<PropertySaveMeterInfoDTO> dtos = new ArrayList<>();
        for(Map<String,String> roomId : roomIds){
            List<PropertySaveMeterInfoDTO> temps = new ArrayList<>();
            propertySaveMeterInfoDTOs.forEach(d->{
                if(roomId.get("roomId").equals(d.getRoomId())&&roomId.get("month").equals(d.getMonth())&&
                        temps.stream().filter(t-> t.getRoomId().equals(d.getRoomId()) && t.getType().equals(d.getType()) && t.getMonth().equals(d.getMonth())).findFirst().isPresent()==false){
                    temps.add(d);
                }
            });
            PropertySaveMeterInfoDTO dto = new PropertySaveMeterInfoDTO();
            dto.setBuildId(temps.get(0).getBuildId());
            dto.setUnitId(temps.get(0).getUnitId());
            dto.setRoomId(temps.get(0).getRoomId());
            dto.setProjectId(propertySaveMeterInfoDTOs.get(0).getProjectId());
            dto.setMonth(temps.get(0).getMonth());
            dto.setSaveType("1");
            dto.setAddressName(roomId.get("address"));
            for(PropertySaveMeterInfoDTO temp : temps){
                PropertySaveMeterInfoSubDTO subDto = new PropertySaveMeterInfoSubDTO();
                subDto.setType(Integer.valueOf(temp.getType()));
                subDto.setFeeRuleId(iPropertyPaymentManageDao.getRuleIdByRuleName(propertySaveMeterInfoDTOs.get(0).getProjectId(), temp.getRule(),1));
                subDto.setStart(Integer.valueOf(temp.getStart()));
                subDto.setEnd(Integer.valueOf(temp.getEnd()));
                subDto.setLossAmount(temp.getLossAmount());
                if(StringUtils.isNotBlank(subDto.getFeeRuleId())) {
                    dto.getFees().add(subDto);
                }
            }
            dtos.add(dto);
        }
        for(PropertySaveMeterInfoDTO dto : dtos){
            if(dto.getFees().size()<3){
                return dto.getAddressName();
            }
        }
        for(PropertySaveMeterInfoDTO dto : dtos){
            this.saveOrUpdateMemterInfo(dto);
        }
        return null;
    }

    /**
     * <desc>
     *      检测当前房间是否有业主
     * </desc>
     *
     * @param roomId
     * @return
     * @author Jiaqi.X
     * @createDate 2018/09/03
     */
    @Override
    public Integer checkRoomHaveOwner(String roomId){
        return iPropertyPaymentManageDao.checkRoomHaveOwner(roomId);
    }

    /**
     * <desc>
     *      检查房间是否存在
     * </desc>
     *
     * @param address
     * @return
     * @author Jiaqi.X
     * @createDate 2018/09/03
     */
    @Override
    public Integer checkRoomExists(String address,String projectId) {
        String buildName = address.substring(0, address.indexOf("-"));
        address = address.substring(address.indexOf("-") + 1, address.length());
        String unitName =  address.substring(0, address.indexOf("-"));
        address =address.substring(address.indexOf("-") + 1, address.length());
        String roomNum = StringHandlerUtil.autlSupply(4, address.substring(address.indexOf("-", 2) + 1, address.length()), "0");
        Map<String,Object> map = iPropertyPaymentManageDao.getRoomInfoByBuildNameAndUnitNameAndRoomNum(buildName,unitName,roomNum,projectId);
        if(map == null){
            return 1;
        }else if(iPropertyPaymentManageDao.checkRoomHaveOwner(map.get("roomId").toString()) == 0){
            //检查房间是否存在用户
            return 2;
        }else if(iPropertyPaymentManageDao.checkRoomArea(map.get("roomId").toString()) == 0){
            //检查房屋面积是否为空
            return 3;
        }
        return 0;
    }

    /**
     * <desc>
     *      检查收费规则是否存在
     * </desc>
     *
     * @param projectId 项目id
     * @param ruleName 规则名称
     * @return
     * @author Jiaqi.X
     * @createDate 2018/09/03
     */
    @Override
    public boolean checkRuleIsExists(String projectId,String ruleName,Integer type){
        return StringUtils.isBlank(iPropertyPaymentManageDao.getRuleIdByRuleName(projectId, ruleName,type));
    }

    /**
     * <desc>
     *      检测房间面积是否为空
     * </desc>
     *
     * @param roomId
     * @return
     * @author Jiaqi.X
     * @createDate 2018/10/23
     */
    @Override
    public Integer checkRoomArea(String roomId){
        return iPropertyPaymentManageDao.checkRoomArea(roomId);
    }

    /**
     * <desc>
     *      规则变更更改受影响的账单
     * </desc>
     *
     * @param feeRuleId
     * @author Jiaqi.X
     * @createDate 2018/09/04
     */
    @Override
    public void ruleChangeUpdateBill(String feeRuleId) throws Exception {
        //查询与该规则绑定的数据
        List<PropertyPaymentDataRecordPO> list = iPropertyPaymentDataRecordDao.getRecordsByRuleId(feeRuleId);
        List<PropertyPaymentDataRecordPO> listClone = new ArrayList<>();
        listClone.addAll(list);
        Set<String> feeIds = new HashSet<>();
        for(PropertyPaymentDataRecordPO po : list){
            PropertySaveMeterInfoDTO dto = new PropertySaveMeterInfoDTO();
            dto.setFeeDataId(po.getFeeDataId());
            dto.setFeeId(po.getFeeId());
            dto.setProjectId(po.getProjectId());
            dto.setBuildId(po.getBuildId());
            dto.setUnitId(po.getUnitId());
            dto.setRoomId(po.getRoomId());
            dto.setMonth(DateUtil.fomatDate(po.getStartTime(), "yyyy-MM"));
            dto.setFeeRuleId(po.getFeeRuleId());
            if(po.getType()==4){
                dto.setSaveType("2");
            }else if(feeIds.add(dto.getFeeId())){
                dto.setSaveType("1");
                dto.setFeeDataId(null);
                List<PropertySaveMeterInfoSubDTO> subDTOs = new ArrayList<>();
                for(int i = listClone.size()-1;i >=0;i--){
                    if(listClone.get(i).getFeeId().equals(dto.getFeeId()) && listClone.get(i).getType() != 4){
                        PropertySaveMeterInfoSubDTO d = new PropertySaveMeterInfoSubDTO();
                        d.setFeeDataId(listClone.get(i).getFeeDataId());
                        d.setFeeId(listClone.get(i).getFeeId());
                        d.setType(listClone.get(i).getType());
                        d.setFeeRuleId(listClone.get(i).getFeeRuleId());
                        d.setStart(listClone.get(i).getStart());
                        d.setEnd(listClone.get(i).getEnd());
                        d.setLossAmount(listClone.get(i).getLossAmount()!=null ? listClone.get(i).getLossAmount().toString() : null);
                        subDTOs.add(d);
                        listClone.remove(i);
                    }
                }
                dto.setFees(subDTOs);
            }else{
                continue;
            }
            this.saveOrUpdateMemterInfo(dto);
        }
    }
}
